<?php

namespace Lite;

require_once dirname(__FILE__) . '/../../src/Lite.php';

/**
 * Session test case.
 */
class SessionTest extends \PHPUnit_Framework_TestCase {
	
	/**
	 * @var Session
	 */
	private $Session;
	
	/**
	 * Prepares the environment before running a test.
	 */
	protected function setUp() {
		parent::setUp();
	}
	
	/**
	 * Cleans up the environment after running a test.
	 */
	protected function tearDown() {
		parent::tearDown();
		
		if(!$this->Session instanceof Session) {
			$this->Session = Session::getInstance();
		}
		
		$this->Session->destroy();
		unset( $this->Session );
		Session::unsetInstance();
	}
	
	function __construct() {
		ob_start();
	}

	/**
	 * Tests Session::setSessionId()
	 */
	public function testSetSessionId() {
		$sessionId = 'testing';
		
		if( Session::isStarted() ) {
			$this->hasFailed();
		}
		
		Session::setSessionId( $sessionId );
		$this->Session = Session::getInstance();
		
		$this->assertTrue( Session::isStarted() );
		
		$this->assertEquals( $sessionId,  $this->Session->getId() );
		
		try {
			$sessionId = strrev($sessionId);
			Session::setSessionId($sessionId);
			$this->hasFailed();
		}catch(RuntimeException $exp){
			// success!
		}
	}
	
	/**
	 * Tests Session::setSessionHandler()
	 */
	public function testSetSessionHandler() {
		$this->markTestIncomplete ( "setSessionHandler test not implemented" );
		# Session::setSessionHandler(/* parameters */);
	}
	
	/**
	 * Tests Session::isStarted()
	 */
	public function testIsStarted() {
			
		$this->assertFalse(Session::isStarted());
		
		$this->Session = Session::getInstance();
		
		$this->assertTrue(Session::isStarted());
		
		$this->Session->close();
				
		$this->assertFalse(Session::isStarted());
		
		$this->Session->open();
		
		$this->assertTrue(Session::isStarted());
		
		Session::unsetInstance();
		
		$this->assertFalse(Session::isStarted());
		
	}
	
	/**
	 * Tests Session::getInstance()
	 */
	public function testGetInstance() {
		
		$this->assertArrayNotHasKey( '_SESSION', $GLOBALS );
		
		$session1 = Session::getInstance();
		$session2 = Session::getInstance();
		
		$this->assertArrayHasKey( '_SESSION', $GLOBALS );
		
		$this->assertSame( $session1, $session2);
	}
	
	/**
	 * Tests Session->__get()
	 */
	public function test__get() {
		$this->Session = Session::getInstance();
		
		$key1 = 'key-1';
		$key2 = 'key-2';
		
		$value1 = 'value-1';
		$value2 = 'value-2';
		
		$this->assertEquals( null, $this->Session->__get($key1));
		$this->assertEquals( null, $this->Session->{$key2});
		
		$_SESSION[ $key1 ] = $value1;
		$_SESSION[ $key2 ] = $value2;
		
		$this->assertEquals( $value1, $this->Session->__get($key1));
		$this->assertEquals( $value2, $this->Session->{$key2});
	}
	
	/**
	 * Tests Session->getValue()
	 */
	public function testGetValue() {
		$this->Session = Session::getInstance();
		
		$key1 = 'key-1';
		$key2 = 'key-2';
		
		$value1 = 'value-1';
		$value2 = 'value-2';
		
		$this->assertEquals( null, $this->Session->getValue($key1));
		$this->assertEquals( null, $this->Session->getValue($key2));
		
		$_SESSION[ $key1 ] = $value1;
		$_SESSION[ $key2 ] = $value2;
		
		$this->assertEquals( $value1, $this->Session->getValue($key1));
		$this->assertEquals( $value2, $this->Session->getValue($key2));
	}
	
	/**
	 * Tests Session->__set()
	 */
	public function test__set() {
		$this->Session = Session::getInstance();
		
		$key1 = 'key-1';
		$key2 = 'key-2';
		
		$value1 = 'value-1';
		$value2 = 'value-2';
		
		$this->assertArrayNotHasKey($key1, $_SESSION);
		$this->assertArrayNotHasKey($key2, $_SESSION);
		
		$this->assertEquals($value2, $this->Session->__set($key2, $value2));
		$this->assertEquals($value1, $this->Session->{$key1} = $value1 );
		
		$this->assertTrue( $this->Session->hasKey($key1));
		$this->assertTrue( $this->Session->hasKey($key2));
		
		$this->assertArrayHasKey($key1, $_SESSION);
		$this->assertArrayHasKey($key2, $_SESSION);
	}
	
	/**
	 * Tests Session->addKey()
	 */
	public function testAddKey() {
		$this->Session = Session::getInstance();
		
		$key = 'key-value';
		$value = 'value-value';
		
		$this->assertArrayNotHasKey($key, $_SESSION);
				
		$this->assertEquals($value, $this->Session->addKey($key, $value));
				
		$this->assertTrue( $this->Session->hasKey($key));
		$this->assertArrayHasKey($key, $_SESSION);
	}
	
	/**
	 * Tests Session->__isset()
	 */
	public function test__isset() {
		$this->Session = Session::getInstance();
		
		$key = 'key-value';
		$value = 'value-value';
		
		$this->assertArrayNotHasKey($key, $_SESSION);
		
		$this->assertFalse( $this->Session->__isset($key));
		$this->assertFalse( isset( $this->Session->{$key}));
		
		$this->Session->addKey($key, $value);

		$this->assertTrue( $this->Session->__isset($key));
		$this->assertTrue( isset( $this->Session->{$key}));
	}
	
	/**
	 * Tests Session->hasKey()
	 */
	public function testHasKey() {
		$this->Session = Session::getInstance();
		
		$key = 'key-value';
		$value = 'value-value';
		
		$this->assertArrayNotHasKey($key, $_SESSION);
		
		$this->assertFalse( $this->Session->__isset($key));
		$this->assertFalse( isset( $this->Session->{$key}));
		
		$this->Session->addKey($key, $value);

		$this->assertTrue( $this->Session->__isset($key));
		$this->assertTrue( isset( $this->Session->{$key}));
	}
	
	/**
	 * Tests Session->__unset()
	 */
	public function test__unset() {
		
		$this->Session = Session::getInstance();
		
		$key1 = 'key1-value';
		$key2 = 'key2-value';
		
		$value1 = 'value1-value';
		$value2 = 'value2-value';
		
		$this->assertArrayNotHasKey($key1, $_SESSION);
		$this->assertFalse( $this->Session->hasKey($key2));
				
		$this->Session->addKey($key1, $value1);
		$this->Session->addKey($key2, $value2);

		$this->assertArrayHasKey($key1, $_SESSION);
		$this->assertTrue( $this->Session->hasKey($key2));
		
		$this->Session->__unset($key1);
		unset($this->Session->{$key2});
		
		$this->assertArrayNotHasKey($key1, $_SESSION);
		$this->assertFalse( $this->Session->hasKey($key2));
	}
	
	/**
	 * Tests Session->removeKey()
	 */
	public function testRemoveKey() {
		$this->Session = Session::getInstance();
		
		$key = 'key-value';
		$value = 'value-value';
		
		$this->assertArrayNotHasKey($key, $_SESSION);
		$this->assertFalse( $this->Session->hasKey($key));
				
		$this->Session->addKey($key, $value);
		
		$this->assertArrayHasKey($key, $_SESSION);
		$this->assertTrue( $this->Session->hasKey($key));
		
		$this->Session->removeKey($key);
		
		$this->assertArrayNotHasKey($key, $_SESSION);
		$this->assertFalse( $this->Session->hasKey($key));
	}
	
	/**
	 * Tests Session->close()
	 */
	public function testClose() {
		$this->Session = Session::getInstance();
		
		$this->assertTrue( $this->Session->isOpen() );
		
		$key1 = 'key-1';
		$key2 = 'key-2';
		$key3 = 'key-3';
		
		$value1= 'value-1';
		$value2= 'value-2';
		$value3= 'value-3';
		
		$_SESSION[ $key1 ]  = $value1;
		
		$this->Session->close();
		
		$this->assertFalse( $this->Session->isOpen() );
		
		$_SESSION[ $key2 ]  = $value2;
		$this->Session->addKey($key3, $value3);
		
		$this->Session->open();
		
		$this->assertTrue( $this->Session->isOpen() );
		
		$this->assertArrayHasKey( $key1, $_SESSION );
		$this->assertArrayNotHasKey( $key2, $_SESSION );
		$this->assertArrayNotHasKey( $key3, $_SESSION );
		
		$this->assertTrue( $this->Session->hasKey($key1));
		$this->assertFalse( $this->Session->hasKey($key2));
		$this->assertFalse( $this->Session->hasKey($key3));
	}
	
	/**
	 * Tests Session->destroy()
	 */
	public function testDestroy() {
		$this->Session = Session::getInstance();
		
		$this->Session->addKey('a', '1');
		$this->Session->addKey('b', '2');
		$this->Session->addKey('c', '3');
		$this->Session->addKey('d', '4');
		
		$this->assertArrayHasKey('a', $_SESSION);
		$this->assertArrayHasKey('b', $_SESSION);
		$this->assertArrayHasKey('c', $_SESSION);
		$this->assertArrayHasKey('d', $_SESSION);
		
		$this->Session->destroy();
		
		$this->assertArrayNotHasKey('a', $_SESSION);
		$this->assertArrayNotHasKey('b', $_SESSION);
		$this->assertArrayNotHasKey('c', $_SESSION);
		$this->assertArrayNotHasKey('d', $_SESSION);
	}
	
	/**
	 * Tests Session->getId()
	 */
	public function testGetId() {
		$sessionId = 'PHP-SESSION-ID';
		
		Session::setSessionId( $sessionId );
		
		$this->Session = Session::getInstance();
		
		$this->assertEquals( $sessionId, $this->Session->getId());
	
	}
	
	/**
	 * Tests Session->regenerateId()
	 */
	public function testRegenerateId() {
		$this->Session = Session::getInstance();
		
		$sessionId = $this->Session->getId();
		$this->Session->regenerateId();
		$this->assertNotEquals( $sessionId, $this->Session->getId());
	}

}

